{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "NvFMw17BoLbq"
   },
   "source": [
    "##### Copyright 2020 Google"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "cellView": "form",
    "id": "CvJ_QrYPoM8L"
   },
   "outputs": [],
   "source": [
    "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "# https://www.apache.org/licenses/LICENSE-2.0\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "3EidIixoF1Ms"
   },
   "source": [
    "# Quantum Chess REST Client"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "OYeSZNZBoUK2"
   },
   "source": [
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://www.example.org/cirq/experiments/quantum_chess/quantum_chess_client\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />View on QuantumLib</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/quantumlib/ReCirq/blob/master/docs/quantum_chess/quantum_chess_client.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/quantumlib/ReCirq/blob/master/docs/quantum_chess/quantum_chess_client.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a href=\"https://storage.googleapis.com/tensorflow_docs/ReCirq/docs/quantum_chess/quantum_chess_client.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "NsP1vVXYuo_-"
   },
   "source": [
    "This is a basic client meant to test the server implemented at the end of the  [Quantum Chess REST API](./quantum_chess_rest_api.ipynb) documentation. You must run that previous Colab for this one to work."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "b3600ee25c8e"
   },
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "zn40ny5Puj1A"
   },
   "outputs": [],
   "source": [
    "!pip install git+https://github.com/quantumlib/ReCirq/ -q\n",
    "!pip install requests -q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "glA7YB4VxPDL"
   },
   "source": [
    "The server for the Quantum Chess Rest API endpoints should provide you with an ngrok url when you run it. **Paste the url provided by your server in the form below**. If your server is running, the following code should produce the message: \"Running Flask on Google Colab!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "4JOEEu-ewQ-X"
   },
   "outputs": [],
   "source": [
    "url = 'http://bd626d83c9ec.ngrok.io/' #@param {type:\"string\"}\n",
    "!curl -s $url"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pgvtoLl_YltL"
   },
   "source": [
    "You should be able to see the server output indicting a connection was made."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8GewRWMqGe0G"
   },
   "source": [
    "## Initialization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "0Lm1rW1TXUzI"
   },
   "source": [
    "Make a simple request to initialize a board with the starting occupancy state of all pieces. Using the bitboard format, the initial positions of pieces are given by the hex 0xFFFF00000000FFFF. This initializes all squares in ranks 1, 2, 7, and 8 to be occupied."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "YiDU-GISwi5Z"
   },
   "outputs": [],
   "source": [
    "import requests\n",
    "\n",
    "init_board_json = { 'init_basis_state' : 0xFFFF00000000FFFF }\n",
    "response = requests.post(url + '/quantumboard/init', json=init_board_json)\n",
    "\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "e855abc508f0"
   },
   "source": [
    "## Superposition"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CTpB3ARVXiph"
   },
   "source": [
    "With the board initialized, you can execute a few moves to see what happens. You can create superposition by executing a split move from b1 to a3 and c3. Watch the server output to see the execution of this move."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "0dXVki0VTH8u"
   },
   "outputs": [],
   "source": [
    "from recirq.quantum_chess.enums import MoveType, MoveVariant\n",
    "from recirq.quantum_chess.bit_utils import square_to_bit\n",
    "\n",
    "split_b1_a3_c3 = {'square1' : square_to_bit('b1'), 'square2' : square_to_bit('a3'), 'square3' : square_to_bit('c3'), \n",
    "                  'type' : int(MoveType.SPLIT_JUMP.value), 'variant': int(MoveVariant.BASIC.value)}\n",
    "response = requests.post(url + '/quantumboard/do_move', json=split_b1_a3_c3)\n",
    "print(response.content)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "003a7ae0e0fc"
   },
   "source": [
    "## Entanglement"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "mbJ7ogpZXnB_"
   },
   "source": [
    "You can see, in the probabilities returned, a roughly 50/50 split for two of the squares. A pawn two-step move, from c2 to c4, will entangle the pawn on c2 with the piece in superposition on a3 and c3."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "2AmPlYGBygU2"
   },
   "outputs": [],
   "source": [
    "move_c2_c4 = {'square1' : square_to_bit('c2'), 'square2' : square_to_bit('c4'), 'square3' : 0,'type' : int(MoveType.PAWN_TWO_STEP.value), 'variant': int(MoveVariant.BASIC.value)}\n",
    "response = requests.post(url + '/quantumboard/do_move', json=move_c2_c4)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "15903f3609ec"
   },
   "source": [
    "## Measurement"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "n0AxRGrDX62w"
   },
   "source": [
    "The probability distribution returned doesn't show the entanglement, but it still exists in the underlying state. You can see this by doing a move that forces a measurement. An excluded move from d1 to c2 will force a measurement of the c2 square. In the server output you should see the collapse of the state, with c2, c3, c4, and a3 taking definite 0 or 100% probabilities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "_CuMRZxnXIRe"
   },
   "outputs": [],
   "source": [
    "move_d1_c2 = {'square1' : square_to_bit('d1'), 'square2' : square_to_bit('c2'), 'square3' : 0, 'type' : int(MoveType.JUMP.value), 'variant': int(MoveVariant.EXCLUDED.value)}\n",
    "response = requests.post(url + '/quantumboard/do_move', json=move_d1_c2)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WBi1MAw35dEj"
   },
   "source": [
    "You can see the entanglement correlation by running the following cell a few times. There should be two different outcomes, the first with both c2 and c3 are 100%, and the second with c4 and a3 both 100%."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Ioatj4Ty5VNt"
   },
   "outputs": [],
   "source": [
    "response = requests.post(url + '/quantumboard/undo_last_move')\n",
    "print(response.content)\n",
    "response = requests.post(url + '/quantumboard/do_move', json=move_d1_c2)\n",
    "print(response.content)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "quantum_chess_client.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
